/***************************************************************************//**
 * @file mac_transmitter.h
 * @brief for mac transfer data, include LBT,retry,TDMA.
 * @author ze .
 * @date  2022/7/03.
 * @copyright Copyright 
 ******************************************************************************/

#ifndef _MAC_TRANSMITTER_H_
#define _MAC_TRANSMITTER_H_

#include "stdint.h"
#include "stateMachine.h"
#include "softwareMultiTimer.h"

#define ADHOC_RETRY_COUNT_MAX 10   //RETRY重传的最大次数
#define LBT_REDO_COUNT_MAX    10   //LBT重做的最大次数
#define DOWNLINK_CONCURRENCY_CAPABILITY 5 //主动下行点对点并发的数量 不超过16-6 10

#define WAIT_SEND_TIMEOUT     6554// 200ms 65536=2s ，考虑广播
//ToDo 接收状态机 结果为失败时 立即置位ackTimeout false
//#define WAIT_ACK_TIMEOUT      0x800 //表示62.4ms等待应答的超时时间， 留足余量; //6000  //V0.0版本;  .需与RxstateMachine 对齐；单位1/32768s，需根据不同的报文来定义，考虑主机的解包和解密带来的应答时延， 进一步的可开启定时器来延时入接收模式
#ifdef RFM_DEVICE
#define WAIT_ACK_TIMEOUT      1500//考虑注册阶段 1500/32768 = 46ms
#else
#define WAIT_ACK_TIMEOUT      1200//HUB应答超时37ms
#endif

#ifdef RFM_DEVICE
#define ACK_PREAMBLE_LENGTH_BIT    ADHOC_PREAMBLE_LENGTH_BIT//由于HUB存在天线分集，故RFM应答前导码需>=80bit 考虑为ADHOC_PREAMBLE_LENGTH_BIT
#else
#define ACK_PREAMBLE_LENGTH_BIT    40//由于RFM无天线分集，故HUB给出的应答包仅40bit
#endif

#define ADHOC_PREAMBLE_LENGTH_BIT  135  //120//Adhoc的目的地端 均开启FastAutoHop? 120？140天线分集RSSI模式 4.1ms
#define BCAST_PREAMBLE_LENGTH_BIT  1920 // 50ms前导码长度 38.4kbps
#define LBT_THRESHOLD_RSSI  -360        //单位dbm*4, -90*4 = -360

#define CHECK_TRANS_EVENT_TYPE_IS_ACTIVE_UPLINK(a)   (a == EN_TRANS_REQ_ADHOC_UPLINK || a == EN_TRANS_REQ_SPVN)
#define CHECK_TRANS_EVENT_TYPE_IS_ACTIVE_DOWNLINK(a)  ((EN_TRANS_REQ_ADHOC_DOWNLINK_START <= a) && (a <= EN_TRANS_REQ_ADHOC_DOWNLINK_END))
#define CHECK_TRANS_EVENT_TYPE_IS_LBT_NOT_NEED(a)      (a == EN_TRANS_REQ_SYNC_BCAST || a == EN_TRANS_REQ_ADHOC_SPVN_ACK || a == EN_TRANS_REQ_FILE_DATA_TX)
#define CHECK_TRANS_EVENT_TYPE_IS_ACK_NOT_REQ(a)       (CHECK_TRANS_EVENT_TYPE_IS_LBT_NOT_NEED(a)|| a == EN_TRANS_REQ_REALTIME_BCAST)

#define RETRY_CTRL_FLAG_BITMASK_IS_LBT_FAILED  0x01

typedef struct 
{   
    //uint8_t byDestId;//active trans的目的地址,相同地址无缓存，见外部EventDestId
    uint8_t byCrtlFlag; //bit0置1表示 为LBT失败重复报文
    uint8_t byEventType;  //见TRANS_REQ_E
    uint8_t byRetryCount;
    uint8_t byRetryMaxTimes;
    uint32_t bySeq; //由外部传入，主机初始化为1，主机翻转为2，从机初始化为0，保存在device.c中，需从device.h接口访问，供回调校验
    MultiTimer stRetryTimer;
}RETRY_CTRL_ST;

#define GET_DW_BIT_MASK(a) (((uint32_t)0x00000001) << a)
typedef enum 
{
    //按处理优先级顺序排列，最大32个 uint32字符
    EN_TRANS_REQ_SYNC_BCAST = 0,      //由mac_TDMA.c内部 & app产生请求，SYNC BCAST 主动同步广播报文，仅HUB到RFM，前导码长度255字节，需在规划SLOT B1、B2时隙内发送，可强制打断非RF_IDLE状态，进入TX状态；
    EN_TRANS_REQ_ADHOC_SPVN_ACK,      //由mac_receiver.c上层接收处理产生请求，点对点或心跳上报应答，包括HUB到RFM应答，及RFM到HUB应答，及时响应，5ms内可使用接收到的信道直接应答； Todo，从收到数据开始计时15ms，超过应答无意义，可直接取消！  
    EN_TRANS_REQ_FILE_DATA_TX,        //由mac_TDMA.c内部 &app产生请求，File Data 文件数据报文，RFM到HUB，或HUB到RFM单/广播发送，需在规划SLOT F1、F2、F3、F4、F5时隙内TX    
    EN_TRANS_REQ_REALTIME_BCAST,      //由app上层产生请求，Realime bcast，实时广播报文，HUB到RFM，或MHUB到HUB，前导码 长度正常，竞争访问信道，若RF IDLE空闲或LBT通过时才允许发送；
    //EN_TRANS_REQ_ADHOC_SPVN_RETRY,    //由mac_transmitter内的定时器回调产生请求，开始重传，可使用已分配的规划心跳槽；     
    EN_TRANS_REQ_REGISTER,
    EN_TRANS_REQ_ADHOC_UPLINK ,         //由app上层产生请求，点对点上行，RFM->HUB,HUB->MHUB主动发送，包括RFM到HUB，及HUB到RFM，需在非规划SLOT时隙即竞争访问信道，若RF IDLE空闲或LBT通过时才允许发送；
    EN_TRANS_REQ_SPVN ,               //由mac_TDMA.c内部产生请求，SPVN 心跳上报，RFM到HUB，及HUB到MHUB，时间已同步的前提下，首次发送需在规划心跳槽SLOT H1、H2时隙内，重传时竞争访问信道，若RF IDLE空闲或LBT通过时才允许发送；！！！若SPVN产生时正在Adhoc过程，若SPVN时产生Adhoc，则丢弃SPVN并增加Adhoc重传次数
    EN_TRANS_REQ_ADHOC_DOWNLINK_START = EN_TRANS_REQ_SPVN + 1,      //由app上层产生需求，仅HUB有，下行重传控制点对点下行，HUB->多个RFM，MHUB->多个HUB主动发送，会产生多个ACTIVE_TRANS_RETRY_CTRL_BLOCK_ST实例，需缓存多个目的地地址，点对点信息，可并发下行
    EN_TRANS_REQ_ADHOC_DOWNLINK_END = EN_TRANS_REQ_ADHOC_DOWNLINK_START + DOWNLINK_CONCURRENCY_CAPABILITY - 1,
    EN_TRANS_REQ_MAX ,
    EN_TRANS_REQ_NONE 
}TRANS_REQ_E;//Todo最好需有对应的data，如destId等

typedef enum 
{
    /************x to——> TxStateMachine 每个状态对应 等待相应的事件类型*******************/
    EN_MAC_TX_EVENT_TYPE_TRANS_REQ = 0, //Value见TRANS_REQ_E；有事件需无线发送，from x= app/net or mac：RxState\TDMA ,
    EN_MAC_TX_EVENT_TYPE_LBT_CHECK_DONE,
    EN_MAC_TX_EVENT_TYPE_SEND_DONE,
    EN_MAC_TX_EVENT_TYPE_WAIT_ACK_DONE,
    EN_MAC_TX_EVENT_TYPE_TRANS_FINISH,

    EN_MAC_TX_EVENT_TYPE_NONE 
}MAC_TX_EVENT_TYPE_E;

//对应eventType的data
#define SEND_DONE_IS_PASS      0x01
#define WAIT_ACK_DONE_IS_PASS  0x01

typedef enum
{
    EN_MAC_TX_STATE_IDLE_PACKET_ASSEMBLE = 0,
    /*** 作为子状态合并到Idle状态内：
    EN_MAC_TX_STATE_PACKET_ASSEMBLE, 
    EN_MAC_TX_STATE_SLOT_CHECK,
    EN_MAC_TX_STATE_WRITE_FIFO,
    */      
    EN_MAC_TX_STATE_LBT_CHECK,
    EN_MAC_TX_STATE_SEND,
    EN_MAC_TX_STATE_WAIT_ACK,
    /*
    EN_MAC_TX_STATE_RETRY,
    */
    EN_MAC_TX_STATE_SUCCED,
    EN_MAC_TX_STATE_FAILED,

    EN_MAC_TX_STATE_MAX

}MAC_TX_STATE_E;


/**
 * @brief 创建TX回调函数
 * 
 * @param transReqType 待发送的报文类型，
 * @param ppPacket [out] 待发送报文的指针，为出参，由上层访问赋值
 * @param state [in] 当前回调时状态机的状态
 * @param pData [in] 回调的参数，active上报时，为重传控制字ACTIVE_TRANS_RETRY_CTRL_BLOCK_ST
 * @return int >=0: success, -1: fail,not needed
 */
typedef void(*PFUNC_TX_CALLBACK)(uint8_t** ppPacket,MAC_TX_STATE_E currState,void* pData);

/**
 * @brief 注册对应TRANS_REQ_E的TX回调函数
 * 
 * @param PFUNC_TX_CALLBAKC* ppArrayFun，ppArrayFun[TRANS_REQ_E]，与相应的transReq枚举请求事件对应
 * @return void
 */
void macTxStateMachineInit(PFUNC_TX_CALLBACK* ppArrayFun);

/**
 * @brief 注册对应TRANS_REQ_E的TX回调函数
 * 
 * @param pFun 相应的transReq枚举请求事件回调设置，Todo
 * @return void
 */
void macTxCallbackSet(TRANS_REQ_E type, PFUNC_TX_CALLBACK pFun);

/**
 * @brief 检查相应的传输事件请求是否空闲，可以置位传输
 *
 * @param type 待检查的相应的传输请求类型
 * @return 0 >= ok空闲，-1 参数错误，-2 已存在失败，-3正在重传失败
 */
int checkMacTransEvent(TRANS_REQ_E type);//
/**
 * @brief 置位相应的传输事件请求 MacTransEvent
 * 
 * @param type 置位相应的传输请求类型
 * @param destId 相应事件传输的目的地址
 * @param retryMaxTimes 为0表示重传retry定时器回调压入，重传设置事件
 * @param lbtMaxTimes  为0表示lbt最大次数，lbt延时定时器回调
 * @return 0 >= ok，-1 参数错误，-2 已存在失败，-3正在重传失败
 */
void setMacTxStateEvent(uint8_t type, bool isPass);
//设置TxAckChannel;
void setTxAckChannel(uint8_t ackCh);
int setMacTransEvent(TRANS_REQ_E type,uint8_t destId,uint8_t retryMaxTimes,uint8_t lbtMaxTimes);
uint32_t getMacTransEventBitMask();
//pEvent出参,若有事件则赋值， true 表示有事件待处理，需阻止休眠，ToDo该函数用作休眠判断函数块内，休眠函数块前后需临界保护之
bool macTxStateMachineEventCheck(STATEM_TYPE_ST* pEvent);
int macTxStateMachineRun(STATEM_TYPE_ST* pEvent);
bool isTxStateRfIdle();
TRANS_REQ_E getMacTxStateHandlingEventType();
#endif//
